import traceback
from flask import Flask, request, jsonify, send_from_directory, session, redirect, url_for
import os
from func.dao import Database
from werkzeug.security import generate_password_hash, check_password_hash
from func.user_service import (
    is_valid_email, register_user, login_user, get_user_profile as get_user_profile_service,
    get_user_addresses, add_user_address, update_user_address, delete_user_address,
    get_address_by_id, update_user_avatar, update_user_password, update_user_description, get_user_profile_by_id
)
from func.product_service import (
    get_products_by_page, search_products, get_product_details,
    get_user_products, get_user_favorites, get_user_transactions,
    get_product_comments, add_product_comment, delete_product_comment,
    toggle_product_favorite, get_product_images as get_product_images_service, add_product_image,
    delete_product_image as delete_product_image_service, add_product, update_favorite_view_time, update_product, delete_product, update_product_seller_view_time
)
from func.email_service import send_verification_code, verify_code
from flask_cors import CORS
from werkzeug.utils import secure_filename
import time

def create_app():
    app = Flask(__name__)
    CORS(app)
    app.secret_key = os.urandom(24)  # 用于session加密
    app.static_folder = 'static'

    # 创建数据目录
    if not os.path.exists('data'):
        os.makedirs('data')

    # 初始化数据库路径
    from config import DB_PATH

    # 初始化数据库
    db = Database(DB_PATH)

    # 添加允许的图片文件扩展名
    ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
    
    def allowed_file(filename):
        return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

    @app.route('/')
    def index():
        if 'user' not in session:
            return redirect('/login.html')
        return send_from_directory('static', 'index.html')
    
    @app.route('/favicon.ico', methods=['GET'])
    def favicon():
        return send_from_directory('static/images', 'logo.svg')

    @app.route('/<path:path>')
    def serve_static(path):
        response = send_from_directory('static', path)
        return response

    @app.route('/api/send-verification-code', methods=['POST'])
    def send_code():
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        email = data.get('email')
        
        if not email:
            return jsonify({"error": "邮箱不能为空"}), 400
        
        if not is_valid_email(email):
            return jsonify({"error": "邮箱必须是@pku.edu.cn或@stu.pku.edu.cn结尾"}), 400
        
        try:
            code_id = send_verification_code(db, email)
            return jsonify({"message": "验证码已发送"}), 200
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/register', methods=['POST'])
    def register():
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        email = data.get('email')
        password = data.get('password')
        nickname = data.get('nickname', email)
        verification_code = data.get('verification_code')
        
        if not email or not password:
            return jsonify({"error": "邮箱和密码不能为空"}), 400
        
        if not verification_code:
            return jsonify({"error": "验证码不能为空"}), 400
        
        if not is_valid_email(email):
            return jsonify({"error": "邮箱必须是@pku.edu.cn或@stu.pku.edu.cn结尾"}), 400
        
        try:
            # 验证验证码
            if not verify_code(db, email, verification_code):
                return jsonify({"error": "验证码错误或已过期"}), 400
            
            # 对密码进行加密
            hashed_password = generate_password_hash(password)
            register_user(db, email, hashed_password, nickname)
            return jsonify({"message": "注册成功"}), 201
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/login', methods=['POST'])
    def login():
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        email = data.get('email')
        password = data.get('password')
        
        if not email or not password:
            return jsonify({"error": "邮箱和密码不能为空"}), 400
        
        try:
            # 获取用户信息（包含加密后的密码）
            user = get_user_profile_service(db, email)
            # 验证密码
            if not check_password_hash(user['password'], password):
                return jsonify({"error": "邮箱或密码错误"}), 401
                
            session['user'] = email
            return jsonify({"message": "登录成功"})
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/logout', methods=['POST'])
    def logout():
        session.pop('user', None)
        return jsonify({"message": "已退出登录"})

    @app.route('/api/check-auth', methods=['GET'])
    def check_auth():
        if 'user' in session:
            return jsonify({"authenticated": True, "email": session['user']})
        return jsonify({"authenticated": False}), 401

    @app.route('/api/products', methods=['GET'])
    def get_products():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        start_index = int(request.args.get('start', 0))
        count = int(request.args.get('count', 10))
        keyword = request.args.get('keyword')
        
        try:
            if keyword:
                products = search_products(db, keyword)
            else:
                products = get_products_by_page(db, start_index, count)
            return jsonify(products)
        except Exception as e:
            print(str(e))
            print(traceback.format_exc())
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>', methods=['GET'])
    def get_product(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            product = get_product_details(db, product_id)
            seller = get_user_profile_by_id(db, product['seller_id'])
            seller['name'] = seller['nickname']
            product['seller'] = seller

            favorite_products = get_user_favorites(db, session['user'])
            favorite_product_ids = [product['id'] for product in favorite_products]
            product['is_favorite'] = product_id in favorite_product_ids

            if not product:
                return jsonify({"error": "商品不存在"}), 404
            
            return jsonify(product)
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/favorite', methods=['POST'])
    def toggle_favorite(product_id):
        if 'user' not in session:
            return jsonify({'error': '请先登录'}), 401
        
        try:
            success = toggle_product_favorite(db, product_id, session['user'])
            return jsonify({'message': '操作成功', 'status': 'success'}), 200
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/comments', methods=['GET'])
    def get_comments(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            comments = get_product_comments(db, product_id)
            # {'id': 1, 'product_id': 1, 'user_id': 2, 'parent_comment_id': None, 'content': '我是学生，送我！！！', 'created_at': '2025-05-24 09:41:32'}
            user_cache = {}
            for comment in comments:
                if comment['user_id'] not in user_cache:
                    user_cache[comment['user_id']] = get_user_profile_by_id(db, comment['user_id'])
                comment['user'] = user_cache[comment['user_id']]
            return jsonify({
                "comments": comments,
                "status": "success"
            })
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/comments', methods=['POST'])
    def add_comment(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        comment = data.get('comment')
        if not comment:
            content = data.get('content')
            parent_comment_id = data.get('parent_comment_id', -1)
        else:
            content = comment.get('content')
            parent_comment_id = comment.get('parent_comment_id', -1)
        
        if not content:
            return jsonify({"error": "评论内容不能为空"}), 400
        
        try:
            comment_id = add_product_comment(db, product_id, session['user'], content, parent_comment_id)
            return jsonify({"message": "评论成功", "comment_id": comment_id}), 201
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/comments/<int:comment_id>', methods=['DELETE'])
    def delete_comment(product_id, comment_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            success = delete_product_comment(db, comment_id)
            return jsonify({"message": "评论已删除"}), 200
        except Exception as e:
            return jsonify({"error": str(e)}), 500
        
    @app.route('/api/user/<int:user_id>/contact', methods=['POST'])
    def contact_user(user_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            print(user_id)
            profile = get_user_profile_by_id(db, user_id)
            print(profile)
            if not profile:
                return jsonify({"error": "用户不存在"}), 404
            
            return jsonify({
                "message": "消息发送成功",
                "status": "success",
                "contact": profile['email']
            }), 200
        except Exception as e:
            return jsonify({"error": str(e)}), 500
            
    @app.route('/api/user/profile', methods=['GET'])
    def get_user_profile():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取用户基本信息
            user = get_user_profile_service(db, session['user'])
            print(session['user'])
            print(user)
            
            # 获取用户发布的商品
            published_products = get_user_products(db, session['user'])
            # 获取用户收藏的商品
            favorite_products = get_user_favorites(db, session['user'])
            # 获取用户交易记录
            transactions = get_user_transactions(db, session['user'])
            
            return jsonify({
                "id": user['id'],
                "nickname": user['nickname'],
                "description": user['description'],
                "avatar": user['avatar'],
                "email": user['email'],
                "address": user['address'],
                "created_at": user['created_at'],
                "products": published_products,
                "favorites": favorite_products,
                "transactions": transactions,
                "status": "success"
            })
        except Exception as e:
            print(str(e))
            print(traceback.format_exc())
            return jsonify({"error": str(e)}), 500

    @app.route('/api/user/address', methods=['PUT'])
    def update_address():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        new_address = data.get('address')
        
        if not new_address:
            return jsonify({"error": "地址不能为空"}), 400
        
        try:
            success = update_user_address(db, session['user'], new_address)
            return jsonify({"message": "地址更新成功", "status": "success"}), 200
        except Exception as e:
            return jsonify({"error": str(e), "status": "error"}), 500

    @app.route('/api/user/avatar', methods=['POST'])
    def change_avatar():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
            
        if 'image' not in request.files:
            return jsonify({"error": "没有上传文件"}), 400
            
        file = request.files['image']
        if file.filename == '':
            return jsonify({"error": "没有选择文件"}), 400
            
        if file and allowed_file(file.filename):
            # 获取文件扩展名
            file_ext = file.filename.rsplit('.', 1)[1].lower()
            
            try:
                # 获取用户信息
                user_email = session['user']
                user = get_user_profile_service(db, user_email)
                
                # 创建用户头像目录
                user_dir = os.path.join('static/images/users', str(user['id']))
                if not os.path.exists(user_dir):
                    os.makedirs(user_dir)
                
                # 删除旧头像
                old_avatar_path = os.path.join('static', user['avatar'])
                if os.path.exists(old_avatar_path) and not old_avatar_path.endswith("default_head.png"):
                    os.remove(old_avatar_path)
                
                # 保存新头像
                new_filename = f"avatar.{file_ext}"
                new_file_path = os.path.join(user_dir, new_filename)
                file.save(new_file_path)
                
                # 更新用户头像路径
                new_avatar_path = f"images/users/{user['id']}/{new_filename}"
                update_user_avatar(db, session['user'], new_avatar_path)
                
                return jsonify({
                    "status": "success",
                    "message": "头像更新成功",
                    "avatar": f"/{new_avatar_path}"
                }), 200
                
            except Exception as e:
                return jsonify({"error": str(e)}), 500
        else:
            return jsonify({"error": "不支持的文件类型"}), 400
        
    @app.route('/api/product/image/<int:product_id>', methods=['POST'])
    def upload_product_image(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
            
        if "images" in request.files:
            files = request.files.getlist('images')
        elif "image" in request.files:
            files = [request.files['image']]
        else:
            print("error: 没有上传文件")
            print(request)
            return jsonify({"error": "没有上传文件"}), 400
            
        for file in files:
            if file.filename == '':
                return jsonify({"error": "没有选择文件"}), 400
            if file and allowed_file(file.filename):
                try:
                    # 获取文件扩展名
                    file_ext = file.filename.rsplit('.', 1)[1].lower()
                    
                    # 创建商品图片目录
                    product = get_product_details(db, product_id)
                    product_dir = os.path.join('static', product['image_folder'])
                    if not os.path.exists(product_dir):
                        os.makedirs(product_dir)
                    
                    # 生成唯一的文件名
                    timestamp = int(time.time() * 1000)
                    new_filename = f"{timestamp}.{file_ext}"
                    new_file_path = os.path.join(product_dir, new_filename)
                    
                    # 保存图片文件
                    file.save(new_file_path)
                    
                    # 将图片信息保存到数据库
                    image_path = f"{product['image_folder']}/{new_filename}"
                    image_id = add_product_image(db, product_id, image_path)
                    
                except Exception as e:
                    return jsonify({"error": str(e)}), 500
            else:
                return jsonify({"error": "不支持的文件类型"}), 400
        
        product_images = get_product_images_service(db, product_id)
        product_images = [f"/{image['image_path']}" for image in product_images]

        return jsonify({
            "message": "图片上传成功",
            "status": "success",
            "image_id": image_id,
            "image_url": f"/{image_path}",
            "images": product_images
        }), 201
    
    @app.route('/api/product/image/<int:product_id>/<int:image_id>', methods=['DELETE'])
    def delete_product_image(product_id, image_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取图片信息
            images = get_product_images(db, product_id)
            image_to_delete = next((img for img in images if img['id'] == image_id), None)
            
            if not image_to_delete:
                return jsonify({"error": "图片不存在"}), 404
            
            # 删除物理文件
            image_path = os.path.join('static', image_to_delete['image_path'])
            if os.path.exists(image_path):
                os.remove(image_path)
            
            # 从数据库中删除图片记录
            success = delete_product_image_service(db, image_id)
            
            if success:
                return jsonify({"message": "图片删除成功"}), 200
            else:
                return jsonify({"error": "图片删除失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/product/image/<int:product_id>', methods=['GET'])
    def get_product_images(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取商品的所有图片信息
            images = get_product_images_service(db, product_id)
            
            # 为每个图片添加完整的URL
            for image in images:
                image['url'] = f"/{image['image_path']}"
            
            return jsonify(images)
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/user/password', methods=['PUT'])
    def change_password():
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        email = data.get('user')
        old_password = data.get('old_password')
        new_password = data.get('new_password')

        if not email:
            return jsonify({"error": "用户邮箱不能为空"}), 401
        
        if not old_password or not new_password:
            return jsonify({"error": "旧密码和新密码不能为空"}), 400
        
        try:
            # 获取用户信息
            user = get_user_profile_service(db, email)
            
            # 验证旧密码
            if not check_password_hash(user['password'], old_password):
                return jsonify({"error": "旧密码错误"}), 401
            
            # 加密新密码
            hashed_new_password = generate_password_hash(new_password)

            # 更新密码
            success = update_user_password(db, email, hashed_new_password)

            if success:
                return jsonify({"message": "密码修改成功"}), 200
            else:
                return jsonify({"error": "密码修改失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products', methods=['POST'])
    def create_product():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        name = data.get('name')
        description = data.get('description')
        price = data.get('price')

        if not name or not description or not price:
            return jsonify({"error": "商品名称、描述和价格不能为空"}), 400
        
        try:
            # 创建商品图片目录
            timestamp = int(time.time() * 1000)
            image_folder = f"images/products/{timestamp}"
            if not os.path.exists(os.path.join('static', image_folder)):
                os.makedirs(os.path.join('static', image_folder))
            
            # 添加商品
            product_id = add_product(
                db,
                session['user'],
                name,
                description,
                float(price),
                image_folder
            )
            
            return jsonify({
                "message": "商品发布成功",
                "status": "success",
                "product_id": product_id,
                "image_folder": image_folder
            }), 201
            
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>', methods=['PUT'])
    def update_product_route(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        if not request.is_json:
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        name = data.get('name')
        description = data.get('description')
        price = data.get('price')
        
        if not name or not description or not price:
            return jsonify({"error": "商品名称、描述和价格不能为空"}), 400
        
        try:
            # 获取商品信息
            product = get_product_details(db, product_id)
            if not product:
                return jsonify({"error": "商品不存在"}), 404
            
            # 验证是否是商品卖家
            if product['seller_id'] != get_user_profile_service(db, session['user'])['id']:
                return jsonify({"error": "只有商品卖家才能修改商品信息"}), 403
            
            # 更新商品信息
            success = update_product(
                db,
                product_id,
                name,
                description,
                float(price)
            )
            
            if success:
                return jsonify({"message": "商品信息更新成功", "status": "success"}), 200
            else:
                return jsonify({"error": "商品信息更新失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>', methods=['DELETE'])
    def delete_product_route(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取商品信息
            product = get_product_details(db, product_id)
            if not product:
                return jsonify({"error": "商品不存在"}), 404
            
            # 验证是否是商品卖家
            if product['seller_id'] != get_user_profile_service(db, session['user'])['id']:
                return jsonify({"error": "只有商品卖家才能删除商品"}), 403
            
            # 删除商品
            success = delete_product(db, product_id)
            
            if success:
                return jsonify({"message": "商品删除成功"}), 200
            else:
                return jsonify({"error": "商品删除失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/seller-view', methods=['POST'])
    def update_product_seller_view_time_route(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取商品信息
            product = get_product_details(db, product_id)
            if not product:
                return jsonify({"error": "商品不存在"}), 404
            
            # 验证是否是商品卖家
            if product['seller_id'] != get_user_profile_service(db, session['user'])['id']:
                return jsonify({"error": "只有商品卖家才能更新查看时间"}), 403
            
            # 更新查看时间
            success = update_product_seller_view_time(db, product_id)
            
            if success:
                return jsonify({"message": "查看时间更新成功"}), 200
            else:
                return jsonify({"error": "查看时间更新失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/products/<int:product_id>/favorite-view', methods=['POST'])
    def update_favorite_view_time_route(product_id):
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        try:
            # 获取商品信息
            product = get_product_details(db, product_id)
            if not product:
                return jsonify({"error": "商品不存在"}), 404
            
            # 检查是否已收藏
            user = get_user_profile_service(db, session['user'])
            favorite_products = get_user_favorites(db, user['id'])
            if product_id not in [favorite['product_id'] for favorite in favorite_products]:
                return jsonify({"error": "未收藏该商品"}), 400
            
            # 更新查看时间
            success = update_favorite_view_time(db, session['user'], product_id)
            
            if success:
                return jsonify({"message": "查看时间更新成功"}), 200
            else:
                return jsonify({"error": "查看时间更新失败"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    @app.route('/api/user/description', methods=['PUT'])
    def update_description():
        if 'user' not in session:
            return jsonify({"error": "未登录"}), 401
        
        if not request.is_json:
            print(request)
            return jsonify({"error": "请发送JSON数据"}), 400
        
        data = request.get_json()
        new_description = data.get('description')
        
        if not new_description:
            print("描述不能为空")
            return jsonify({"error": "描述不能为空"}), 400
        
        try:
            success = update_user_description(db, session['user'], new_description)
            
            if success:
                return jsonify({"message": "描述更新成功", "status": "success"}), 200
            else:
                return jsonify({"error": "描述更新失败", "status": "error"}), 500
                
        except Exception as e:
            return jsonify({"error": str(e), "status": "error"}), 500

    return app

if __name__ == '__main__':
    app = create_app()
    
    if not os.path.exists('static'):
        os.makedirs('static')
    
    app.run(host='0.0.0.0', port=8080, debug=True)
